#pragma once

#include <iostream>
#include <sstream> // for stringstream
#include <string>
#include <memory>

#include <jsoncpp/json/json.h>

#define SELF 1 // 用自定义方案 否则用 JSON

const std::string Sep = "\r\n";
const std::string BlankSpace = " ";
// 添加报头
// {Json} -> Header-Seq-{Json}-Seq
bool Encode(std::string &msg)
{
    if (msg.empty())
        return false;
    std::string package = std::to_string(msg.size()) + Sep + msg + Sep;
    msg = package;
    return true;
}

// Header-Seq-{Json}-Seq -> {Json}
bool Decode(std::string &package, std::string *content)
{
    auto pos = package.find(Sep);
    if (pos == std::string::npos)
        return false;
    std::string content_length_str = package.substr(0, pos);
    int content_length = std::stoi(content_length_str);

    // 报文的长度
    int full_length = content_length_str.size() + content_length + 2 * Sep.size();
    int sz = package.size();
    if (sz < full_length)
        return false;
    int sep_sz = Sep.size();
    *content = package.substr(pos + sep_sz, content_length);

    // package 移除拿出的
    package.erase(0, full_length); // 后续网络代码再研究
    return true;
}

// _x _op _y
class Request
{
public:
    Request() {}
    Request(int x, int y, char op)
        : _x(x), _y(y), _op(op)
    {
    }
    // x op y
    bool Serialize(std::string &out_string)
    {
#ifdef SELF
        std::string data_x_str = std::to_string(_x);
        std::string data_y_str = std::to_string(_y);
        out_string = data_x_str + BlankSpace + _op + BlankSpace + data_y_str;
        return true;
#else
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["op"] = _op;

        Json::StreamWriterBuilder wb;
        std::unique_ptr<Json::StreamWriter> w(wb.newStreamWriter());
        std::stringstream ss;
        w->write(root, &ss);
        out_string = ss.str();
        return true;
#endif
    }

    bool Deserialize(std::string &in_string)
    {
#ifdef SELF
        // "x op y" 拿出来
        size_t left = in_string.find(BlankSpace);
        if (left == std::string::npos)
            return false;
        size_t right = in_string.rfind(BlankSpace);
        if (right == std::string::npos)
            return false;
        if (left + BlankSpace.size() + 1 != right)
            return false;

        std::string x_str = in_string.substr(0, left);
        if (x_str.empty())
            return false;

        std::string y_str = in_string.substr(right + BlankSpace.size());
        if (y_str.empty())
            return false;

        _op = in_string[right - 1];
        _x = std::stoi(x_str);
        _y = std::stoi(y_str);
        return true;
#else
        Json::Value root;
        Json::Reader reader;
        bool parsingSuccess = reader.parse(in_string, root);
        if (!parsingSuccess)
        {
            std::cout << "Failed to parse JSON: " << reader.getFormattedErrorMessages() << std::endl;
            return false;
        }

        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _op = root["op"].asInt(); // char 也作为 Int
        return true;
#endif
    }
    void Print()
    {
        std::cout << _x << std::endl;
        std::cout << _y << std::endl;
        std::cout << _op << std::endl;
    }

    int X() const { return _x; }
    int Y() const { return _y; }
    char Op() const { return _op; }

private:
    int _x = 0;
    int _y = 0;
    char _op = 0;
};

class Response
{
public:
    Response() {}
    Response(int result, int code)
        : _result(result), _code(code)
    {
    }
    bool Serialize(std::string &out_string)
    {
#ifdef SELF
        std::string result_str = std::to_string(_result);
        std::string code_str = std::to_string(_code);
        out_string = result_str + BlankSpace + code_str;
        return true;
#else
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::StreamWriterBuilder wb;
        std::unique_ptr<Json::StreamWriter> w(wb.newStreamWriter());
        std::stringstream ss;
        w->write(root, &ss);
        out_string = ss.str();
        return true;
#endif
    }
    bool Deserialize(std::string &in_string)
    {
#ifdef SELF
        // _request _code
        auto mid = in_string.find(BlankSpace);
        if (mid == std::string::npos)
            return false;
        std::string left = in_string.substr(0, mid);
        if (left.empty())
            return false;
        std::string right = in_string.substr(mid + BlankSpace.size());
        if (right.empty())
            return false;

        _result = std::stoi(left);
        _code = std::stoi(right);
        return true;
#else
        Json::Value root;
        Json::Reader reader;
        bool parsingSuccessful = reader.parse(in_string, root);
        if (!parsingSuccessful)
        {
            std::cout << "Failed to parse JSON: " << reader.getFormattedErrorMessages() << std::endl;
            return false;
        }

        _result = root["result"].asInt();
        _code = root["code"].asInt();

        return true;
#endif
    }
    void SetResult(int res) { _result = res; }
    void SetCode(int code) { _code = code; }
    int Result() const { return _result; }
    int Code() const { return _code; }

private:
    int _result = 0; // 结果
    int _code = 0;   // 出错码
};